/* eslint-disable */
const {
  Connection,
  Keypair,
  PublicKey,
  Transaction,
  sendAndConfirmTransaction,
  LAMPORTS_PER_SOL,
  SystemProgram,
} = require('@solana/web3.js');
const {
  getAssociatedTokenAddress,
  getAccount,
  getOrCreateAssociatedTokenAccount,
  transfer,
} = require('@solana/spl-token');
const fs = require('fs');
const axios = require('axios');

// 配置
const DEVNET_RPC = 'https://api.devnet.solana.com';
const BACKEND_API = 'http://localhost:7172';
const TEST_ADDRESSES_FILE = './test-addresses.json';
const PLATFORM_WALLET = '813sZTyqkmUrbcGt1Bbo6dn6oRYC6Mh8og5Uk6EmFMAT';
const TOKEN_CREATION_FEE = 0.2; // 0.2 SOL

/**
 * 加载测试钱包地址
 */
function loadTestAddresses() {
  try {
    const data = fs.readFileSync(TEST_ADDRESSES_FILE, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    console.error('❌ 无法加载测试地址文件:', error.message);
    process.exit(1);
  }
}

/**
 * 从数组创建 Keypair
 */
function createKeypairFromArray(secretKeyArray) {
  return Keypair.fromSecretKey(new Uint8Array(secretKeyArray));
}

/**
 * 创建支付交易并发送到平台钱包
 */
async function createPaymentTransaction(connection, payerKeypair, amount) {
  console.log(`💰 创建支付交易: ${amount} SOL 到平台钱包`);
  
  try {
    const transaction = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: payerKeypair.publicKey,
        toPubkey: new PublicKey(PLATFORM_WALLET),
        lamports: amount * LAMPORTS_PER_SOL,
      }),
    );
    
    const signature = await sendAndConfirmTransaction(
      connection,
      transaction,
      [payerKeypair],
    );
    
    console.log(`✅ 支付交易成功: ${signature}`);
    return signature;
  } catch (error) {
    console.error(`❌ 支付交易失败:`, error.message);
    return null;
  }
}

/**
 * 通过后端API创建代币
 */
async function createTokenViaAPI(walletKeypair, tokenConfig) {
  console.log(`🚀 通过API创建代币: ${tokenConfig.symbol}`);
  
  const connection = new Connection(DEVNET_RPC, 'confirmed');
  
  try {
    // 1. 先创建支付交易
    console.log(`💳 第1步: 创建支付交易 (${TOKEN_CREATION_FEE} SOL)`);
    const paymentSignature = await createPaymentTransaction(
      connection,
      walletKeypair,
      TOKEN_CREATION_FEE,
    );
    
    if (!paymentSignature) {
      throw new Error('支付交易失败');
    }
    
    // 等待交易确认
    console.log('⏳ 等待支付交易确认...');
    await new Promise((resolve) => setTimeout(resolve, 3000));
    
    // 2. 创建代币请求
    console.log('🔨 第2步: 发送代币创建请求');
    const response = await axios.post(`${BACKEND_API}/api/tokens`, {
      ...tokenConfig,
      creator: walletKeypair.publicKey.toString(),
      paymentSignature: paymentSignature,
    });
    
    console.log(
      `✅ 代币创建成功: ${response.data.data.symbol} (${response.data.data.mint})`
    );
    return response.data.data;
  } catch (error) {
    console.error(`❌ 代币创建失败:`, error.response?.data || error.message);
    return null;
  }
}

/**
 * 检查钱包余额
 */
async function checkWalletBalance(connection, publicKey, label) {
  try {
    const balance = await connection.getBalance(publicKey);
    const solBalance = balance / LAMPORTS_PER_SOL;
    console.log(`💰 ${label}: ${solBalance.toFixed(6)} SOL`);
    return solBalance;
  } catch (error) {
    console.error(`❌ 检查${label}余额失败:`, error.message);
    return 0;
  }
}

/**
 * 检查代币余额
 */
async function checkTokenBalance(
  connection,
  walletPublicKey,
  tokenMint,
  label,
) {
  try {
    const tokenAccount = await getAssociatedTokenAddress(
      new PublicKey(tokenMint),
      walletPublicKey,
    );
    
    try {
      const account = await getAccount(connection, tokenAccount);
      const balance = Number(account.amount);
      console.log(
        `🪙 ${label} 代币余额: ${balance} ${tokenMint.slice(0, 8)}...`,
      );
      return balance;
    } catch (error) {
      if (error.name === 'TokenAccountNotFoundError') {
        console.log(`🪙 ${label} 代币余额: 0 (账户不存在)`);
        return 0;
      }
      throw error;
    }
  } catch (error) {
    console.error(`❌ 检查${label}代币余额失败:`, error.message);
    return 0;
  }
}

/**
 * 转账SOL
 */
async function transferSOL(connection, fromKeypair, toPublicKey, amount) {
  console.log(
    `💸 转账 ${amount} SOL 到 ${toPublicKey.toString().slice(0, 8)}...`,
  );
  
  try {
    const transaction = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: fromKeypair.publicKey,
        toPubkey: toPublicKey,
        lamports: amount * LAMPORTS_PER_SOL,
      }),
    );
    
    const signature = await sendAndConfirmTransaction(
      connection,
      transaction,
      [fromKeypair],
    );
    
    console.log(`✅ SOL转账成功: ${signature}`);
    return signature;
  } catch (error) {
    console.error(`❌ SOL转账失败:`, error.message);
    return null;
  }
}

/**
 * 转账代币
 */
async function transferToken(
  connection,
  fromKeypair,
  toPublicKey,
  tokenMint,
  amount,
) {
  console.log(
    `🪙 转账 ${amount} 代币 ${tokenMint.slice(0, 8)}... 到 ${toPublicKey.toString().slice(0, 8)}...`,
  );
  
  try {
    const mintPublicKey = new PublicKey(tokenMint);
    
    // 获取或创建发送方代币账户
    const fromTokenAccount = await getOrCreateAssociatedTokenAccount(
      connection,
      fromKeypair,
      mintPublicKey,
      fromKeypair.publicKey,
    );
    
    // 获取或创建接收方代币账户
    const toTokenAccount = await getOrCreateAssociatedTokenAccount(
      connection,
      fromKeypair, // 由发送方支付账户创建费用
      mintPublicKey,
      toPublicKey,
    );
    
    // 执行转账
    const signature = await transfer(
      connection,
      fromKeypair,
      fromTokenAccount.address,
      toTokenAccount.address,
      fromKeypair,
      amount,
    );
    
    console.log(`✅ 代币转账成功: ${signature}`);
    return signature;
  } catch (error) {
    console.error(`❌ 代币转账失败:`, error.message);
    return null;
  }
}

/**
 * 模拟代币交易
 */
async function simulateTokenTrade(
  connection,
  buyerKeypair,
  sellerKeypair,
  tokenMint,
  tokenAmount,
  solAmount,
) {
  console.log(`\n🔄 模拟代币交易:`);
  console.log(`- 买家: ${buyerKeypair.publicKey.toString().slice(0, 8)}...`);
  console.log(`- 卖家: ${sellerKeypair.publicKey.toString().slice(0, 8)}...`);
  console.log(`- 代币: ${tokenMint.slice(0, 8)}...`);
  console.log(`- 交易数量: ${tokenAmount} 代币 <-> ${solAmount} SOL`);
  
  try {
    // 1. 买家转SOL给卖家
    const solTransfer = await transferSOL(
      connection,
      buyerKeypair,
      sellerKeypair.publicKey,
      solAmount,
    );
    if (!solTransfer) return false;
    
    // 等待确认
    await new Promise((resolve) => setTimeout(resolve, 2000));
    
    // 2. 卖家转代币给买家
    const tokenTransfer = await transferToken(
      connection,
      sellerKeypair,
      buyerKeypair.publicKey,
      tokenMint,
      tokenAmount,
    );
    if (!tokenTransfer) return false;
    
    console.log(`✅ 交易完成！`);
    return true;
  } catch (error) {
    console.error(`❌ 交易失败:`, error.message);
    return false;
  }
}

/**
 * 主测试函数
 */
async function runTokenCreationAndTradingTest() {
  console.log('🎯 开始代币创建和交易测试\n');
  
  // 1. 加载测试钱包
  const testAddresses = loadTestAddresses();
  if (testAddresses.length < 3) {
    console.error('❌ 需要至少3个测试钱包');
    return;
  }
  
  const wallet1 = createKeypairFromArray(testAddresses[0].secretKey);
  const wallet2 = createKeypairFromArray(testAddresses[1].secretKey);
  const wallet3 = createKeypairFromArray(testAddresses[2].secretKey);
  
  console.log('👛 测试钱包:');
  console.log(`- 钱包1: ${wallet1.publicKey.toString()} (${testAddresses[0].balance} SOL)`);
  console.log(`- 钱包2: ${wallet2.publicKey.toString()} (${testAddresses[1].balance} SOL)`);
  console.log(`- 钱包3: ${wallet3.publicKey.toString()} (${testAddresses[2].balance} SOL)\n`);
  
  const connection = new Connection(DEVNET_RPC, 'confirmed');
  
  // 2. 检查初始余额
  console.log('📊 检查初始余额:');
  await checkWalletBalance(connection, wallet1.publicKey, '钱包1');
  await checkWalletBalance(connection, wallet2.publicKey, '钱包2');
  await checkWalletBalance(connection, wallet3.publicKey, '钱包3');
  
  // 3. 每个钱包创建一个代币
  console.log('\n🚀 创建代币阶段:');
  
  const token1Config = {
    name: 'Wallet1 Token',
    symbol: 'W1T',
    decimals: 9,
    supply: '1000000000',
    description: '钱包1创建的测试代币',
    image: 'https://example.com/token1.png',
  };
  
  const token2Config = {
    name: 'Wallet2 Token',
    symbol: 'W2T',
    decimals: 9,
    supply: '2000000000',
    description: '钱包2创建的测试代币',
    image: 'https://example.com/token2.png',
  };
  
  const token3Config = {
    name: 'Wallet3 Token',
    symbol: 'W3T',
    decimals: 9,
    supply: '3000000000',
    description: '钱包3创建的测试代币',
    image: 'https://example.com/token3.png',
  };
  
  // 创建代币（通过API）
  const token1 = await createTokenViaAPI(wallet1, token1Config);
  await new Promise((resolve) => setTimeout(resolve, 3000));
  
  const token2 = await createTokenViaAPI(wallet2, token2Config);
  await new Promise((resolve) => setTimeout(resolve, 3000));
  
  const token3 = await createTokenViaAPI(wallet3, token3Config);
  await new Promise((resolve) => setTimeout(resolve, 3000));
  
  if (!token1 || !token2 || !token3) {
    console.error('❌ 部分代币创建失败，终止测试');
    return;
  }
  
  console.log('\n✅ 所有代币创建完成!');
  
  // 4. 检查创建后的代币余额
  console.log('\n🪙 检查代币余额:');
  await checkTokenBalance(connection, wallet1.publicKey, token1.mint, '钱包1 - Token1');
  await checkTokenBalance(connection, wallet2.publicKey, token2.mint, '钱包2 - Token2');
  await checkTokenBalance(connection, wallet3.publicKey, token3.mint, '钱包3 - Token3');
  
  // 5. 执行代币交易
  console.log('\n💱 开始代币交易测试:');
  
  // 等待一段时间确保所有交易都已确认
  console.log('⏳ 等待5秒后开始交易...');
  await new Promise((resolve) => setTimeout(resolve, 5000));
  
  // 交易1: 钱包1购买钱包2的代币
  console.log('\n=== 交易1: 钱包1购买钱包2的代币 ===');
  const trade1Success = await simulateTokenTrade(
    connection,
    wallet1,
    wallet2,
    token2.mint,
    100000000,
    0.1,
  );
  
  if (trade1Success) {
    await new Promise((resolve) => setTimeout(resolve, 3000));
    await checkTokenBalance(connection, wallet1.publicKey, token2.mint, '钱包1 - Token2');
    await checkWalletBalance(connection, wallet1.publicKey, '钱包1');
    await checkWalletBalance(connection, wallet2.publicKey, '钱包2');
  }
  
  // 交易2: 钱包2购买钱包3的代币
  console.log('\n=== 交易2: 钱包2购买钱包3的代币 ===');
  const trade2Success = await simulateTokenTrade(
    connection,
    wallet2,
    wallet3,
    token3.mint,
    200000000,
    0.2,
  );
  
  if (trade2Success) {
    await new Promise((resolve) => setTimeout(resolve, 3000));
    await checkTokenBalance(connection, wallet2.publicKey, token3.mint, '钱包2 - Token3');
    await checkWalletBalance(connection, wallet2.publicKey, '钱包2');
    await checkWalletBalance(connection, wallet3.publicKey, '钱包3');
  }
  
  // 交易3: 钱包3购买钱包1的代币
  console.log('\n=== 交易3: 钱包3购买钱包1的代币 ===');
  const trade3Success = await simulateTokenTrade(
    connection,
    wallet3,
    wallet1,
    token1.mint,
    150000000,
    0.15,
  );
  
  if (trade3Success) {
    await new Promise((resolve) => setTimeout(resolve, 3000));
    await checkTokenBalance(connection, wallet3.publicKey, token1.mint, '钱包3 - Token1');
    await checkWalletBalance(connection, wallet3.publicKey, '钱包3');
    await checkWalletBalance(connection, wallet1.publicKey, '钱包1');
  }
  
  // 6. 最终余额汇总
  console.log('\n📊 最终余额汇总:');
  console.log('\n--- SOL余额 ---');
  await checkWalletBalance(connection, wallet1.publicKey, '钱包1');
  await checkWalletBalance(connection, wallet2.publicKey, '钱包2');
  await checkWalletBalance(connection, wallet3.publicKey, '钱包3');
  
  console.log('\n--- 代币余额 ---');
  await checkTokenBalance(connection, wallet1.publicKey, token1.mint, '钱包1 - Token1');
  await checkTokenBalance(connection, wallet1.publicKey, token2.mint, '钱包1 - Token2');
  await checkTokenBalance(connection, wallet2.publicKey, token2.mint, '钱包2 - Token2');
  await checkTokenBalance(connection, wallet2.publicKey, token3.mint, '钱包2 - Token3');
  await checkTokenBalance(connection, wallet3.publicKey, token3.mint, '钱包3 - Token3');
  await checkTokenBalance(connection, wallet3.publicKey, token1.mint, '钱包3 - Token1');
  
  // 7. 生成测试报告
  const report = {
    timestamp: new Date().toISOString(),
    wallets: [
      {
        address: wallet1.publicKey.toString(),
        initialBalance: testAddresses[0].balance,
        tokens: [token1.mint],
      },
      {
        address: wallet2.publicKey.toString(),
        initialBalance: testAddresses[1].balance,
        tokens: [token2.mint],
      },
      {
        address: wallet3.publicKey.toString(),
        initialBalance: testAddresses[2].balance,
        tokens: [token3.mint],
      },
    ],
    tokens: [
      { symbol: token1.symbol, mint: token1.mint, creator: wallet1.publicKey.toString() },
      { symbol: token2.symbol, mint: token2.mint, creator: wallet2.publicKey.toString() },
      { symbol: token3.symbol, mint: token3.mint, creator: wallet3.publicKey.toString() },
    ],
    trades: [
      { buyer: wallet1.publicKey.toString(), seller: wallet2.publicKey.toString(), token: token2.mint, success: trade1Success },
      { buyer: wallet2.publicKey.toString(), seller: wallet3.publicKey.toString(), token: token3.mint, success: trade2Success },
      { buyer: wallet3.publicKey.toString(), seller: wallet1.publicKey.toString(), token: token1.mint, success: trade3Success },
    ],
  };
  
  const reportFile = `token-trading-test-report-${Date.now()}.json`;
  fs.writeFileSync(reportFile, JSON.stringify(report, null, 2));
  console.log(`\n📄 测试报告已保存: ${reportFile}`);
  
  console.log('\n🏁 代币创建和交易测试完成！');
}

// 错误处理和主函数执行
process.on('unhandledRejection', (error) => {
  console.error('未处理的Promise拒绝:', error);
  process.exit(1);
});

if (require.main === module) {
  runTokenCreationAndTradingTest().catch(console.error);
}

module.exports = {
  runTokenCreationAndTradingTest,
  createTokenViaAPI,
  simulateTokenTrade,
  loadTestAddresses,
  createKeypairFromArray,
};
